package com.xms.sdk.api.controller;

import com.xms.core.components.QueryColumnSortInfo;
import com.xms.core.model.PagedList;
import com.xms.queryview.entity.QueryView;
import com.xms.queryview.service.IQueryViewFinderService;
import com.xms.schema.entity.Attribute;
import com.xms.schema.entity.RelationShip;
import com.xms.schema.service.attribute.IAttributeFinderService;
import com.xms.schema.service.relationship.IRelationShipFinderService;
import com.xms.sdk.api.model.DataFetchAndAggregateModel;
import com.xms.sdk.core.DynamicData;
import com.xms.sdk.core.query.*;
import com.xms.sdk.service.FetchDescriptor;
import com.xms.sdk.service.IAggregateService;
import com.xms.sdk.service.IFetchDataService;
import com.xms.utils.CollectionUtil;
import com.xms.utils.JsonUtil;
import com.xms.utils.StringUtil;
import com.xms.utils.UUIDUtil;
import com.xms.web.framework.controller.ApiBaseController;
import com.xms.web.framework.model.JsonResultObject;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * DataFetchAndAggregateController
 * </p>
 *
 * @author migo
 * @since 2021/9/13
 */
@RestController
@RequestMapping("{org}/api/data/fetchandaggregate")
public class DataFetchAndAggregateController extends ApiBaseController {
    private IQueryViewFinderService _queryViewFinderService;
    private IRelationShipFinderService _relationShipFinderService;
    private IFetchDataService _fetchService;
    private IAggregateService _aggregateService;
    private IAttributeFinderService _attributeFinderService;

    @Autowired
    public DataFetchAndAggregateController(IQueryViewFinderService queryViewFinderService
            , IRelationShipFinderService relationShipFinderService
            , IFetchDataService fetchDataService
            , IAggregateService aggregateService
            , IAttributeFinderService attributeFinderService) {
        _queryViewFinderService = queryViewFinderService;
        _relationShipFinderService = relationShipFinderService;
        _fetchService = fetchDataService;
        _aggregateService = aggregateService;
        _attributeFinderService = attributeFinderService;
    }

    @ApiOperation("查询视图数据和统计数据")
    @PostMapping("")
    public JsonResultObject post(@RequestBody DataFetchAndAggregateModel model) throws Exception {
        QueryView queryView = null;
        if (UUIDUtil.notEmpty(model.QueryViewId)) {
            queryView = _queryViewFinderService.getById(model.QueryViewId);
        } else if (UUIDUtil.notEmpty(model.EntityId)) {
            queryView = _queryViewFinderService.getDefaultView(model.EntityId);
        } else if (StringUtil.notEmpty(model.EntityName)) {
            queryView = _queryViewFinderService.getDefaultView(model.EntityName);
        } else {
            return JNotFound();
        }
        if (queryView == null) {
            return JNotFound();
        }
        if (!queryView.getIsdefault() && queryView.getAuthorizationenabled()) {
            /*if (!_roleObjectAccessService.Exists(queryView.QueryViewId, QueryViewDefaults.ModuleName, CurrentUser.Roles.Select(n => n.RoleId).ToArray()))
            {
                return JUnauthorized();
            }*/
        }
        model.QueryView = queryView;
        model.EntityId = queryView.getEntityid();

        FetchDescriptor fetch = new FetchDescriptor();
        fetch.page = model.page;
        fetch.pageSize = model.pagesize;
        fetch.fetchConfig = queryView.getFetchconfig();
        fetch.getAll = !model.PagingEnabled;
        if (model.issortbyseted) {
            QueryColumnSortInfo sort = new QueryColumnSortInfo(model.sortby, model.sortdirection == 0);
            fetch.sort = sort;
        }
        //查询关键字
        if (StringUtil.notEmpty(model.Q)) {
            fetch.keyword = model.Q;
            fetch.field = model.QField;
        }
        boolean canFetch = true;
        //filter by relationship
        if (StringUtil.notEmpty(model.RelationShipName)) {
            RelationShip relationship = _relationShipFinderService.getByName(model.RelationShipName);
            if (relationship != null && UUIDUtil.notEmpty(model.ReferencedRecordId)) {
                if (model.Filter == null) {
                    model.Filter = new FilterExpression();
                }
                ConditionExpression condition = new ConditionExpression(relationship.getReferencingattributename(), ConditionOperator.Equal, model.ReferencedRecordId);
                model.Filter.addCondition(condition);
            }
            model.RelationShipMeta = relationship;
        }
        if (StringUtil.notEmpty(model.RelationShipName) && UUIDUtil.notEmpty(model.ReferencedRecordId)) {
            //如果被引用ID为空，则不查询数据
            canFetch = false;
        }
        fetch.filter = model.Filter;
        if (canFetch) {
            fetch.user = _currentUser;
            PagedList<DynamicData> fetchDatas = _fetchService.execute(fetch);
            DynamicData aggregateDatas = null;
            if (StringUtil.notEmpty(queryView.getAggregateconfig())) {
                List<AggregateExpressionField> aggFields = JsonUtil.toList(queryView.getAggregateconfig(), AggregateExpressionField.class);
                if (CollectionUtil.notEmpty(aggFields)) {
                    QueryExpression queryExp = JsonUtil.toBean(queryView.getFetchconfig(), QueryExpression.class);
                    if (model.Filter != null && (CollectionUtil.notEmpty(model.Filter.Conditions)
                            || (CollectionUtil.notEmpty(model.Filter.Filters) && CollectionUtil.notEmpty(model.Filter.Filters.get(0).Conditions)))) {
                        queryExp.Criteria.addFilter(model.Filter);
                    }
                    AggregateExpression aggExp = new AggregateExpression() {
                        {
                            ColumnSet = queryExp.ColumnSet;
                            Criteria = queryExp.Criteria;
                            EntityName = queryExp.EntityName;
                            LinkEntities = queryExp.LinkEntities;
                            AggregateFields = aggFields;
                        }
                    };
                    List<DynamicData> aggDatas = _aggregateService.execute(aggExp);
                    List<Attribute> attributes = _attributeFinderService.getByName(queryView.getEntityid(), aggFields.stream().map(x -> x.AttributeName).collect(Collectors.toList()));
                    for (DynamicData item : aggDatas) {
                        Attribute attribute = attributes.stream().filter(x -> x.getName().equalsIgnoreCase(item.keySet().stream().findFirst().get())).findFirst().get();
                        item.put("metadata", attribute);
                        item.put("aggregatetype", aggFields.stream().filter(x -> x.AttributeName.equalsIgnoreCase(attribute.getName())).findFirst().get().AggregateType.value());
                    }
                    aggregateDatas = new DynamicData();
                    aggregateDatas.setValue("view", new Object[]{
                            queryView.getQueryviewid(),
                            queryView.getName()
                    }).setValue("data", aggDatas);
                }
            }
            return JOk(new DynamicData().setValue("fetchdata", fetchDatas).setValue("aggregatedata", aggregateDatas));
        }
        if (!model.issortbyseted) {
            if (CollectionUtil.notEmpty(fetch.query.Orders)) {
                model.sortby = fetch.query.Orders.get(0).AttributeName;
                model.sortdirection = fetch.query.Orders.get(0).OrderType.val();
            }
        }
        return JOk();
    }
}
